package com.ysten.basic.common.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FTPUtil {
	private static final Logger LOGGER = LoggerFactory.getLogger(FTPUtil.class);
	private static final String UTF_8 = "UTF-8";
	private static final String ROOT = "/";
	private static final int CONNECT_TIMEOUT = 30000;
	private FTPClient ftpClient;
	private String ftpUrl;
	private int ftpPort;
	private String userName;
	private String passWord;
	private String charset;
	private String defaultWorkingDirectory;
	private int connectTimeout;

	public FTPUtil(String ftpUrl, int ftpPort, String userName, String passWord) {
		ftpClient = new FTPClient();
		this.ftpUrl = ftpUrl;
		this.ftpPort = ftpPort;
		this.userName = userName;
		this.passWord = passWord;
	}

	/**
	 * 连接到FTP服务器
	 * 
	 * @param hostname
	 *            主机名
	 * @param port
	 *            端口
	 * @param username
	 *            用户名
	 * @param password
	 *            密码
	 * @return 是否连接成功
	 * @throws IOException
	 */
	public boolean connect() throws IOException {
		return connect(this.ftpUrl, this.ftpPort, this.userName, this.passWord);
	}

	public boolean connect(String ftpUrl, int ftpPort, String userName,
			String passWord) throws IOException {
		String charset = this.charset;
		if (StringUtils.isBlank(charset)) {
			charset = UTF_8;
		}
		if (connectTimeout == 0) {
			connectTimeout = CONNECT_TIMEOUT;
		}
		return connect(this.ftpUrl, this.ftpPort, this.userName, this.passWord,
				charset, connectTimeout);
	}

	private boolean connect(String ftpUrl, int ftpPort, String userName,
			String passWord, String charset, int connectTimeout) throws IOException {
		ftpClient.connect(ftpUrl, ftpPort);
		ftpClient.setConnectTimeout(connectTimeout);
		ftpClient.setControlEncoding(charset);
		if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
			if (ftpClient.login(userName, passWord)) {
				return true;
			}
		}
		disconnect();
		return false;
	}

	/**
	 * 断开与远程服务器的连接
	 * 
	 * @throws IOException
	 */
	public void disconnect() throws IOException {
		if (ftpClient != null && ftpClient.isConnected()) {
			ftpClient.disconnect();
		}
	}

	public void setControlEncoding(String charset) {
		this.charset = charset;
	}
	
	public void setDefaultWorkingDirectory(String workingDirectory) {
		this.defaultWorkingDirectory = workingDirectory;
	}
	
	public void setConnectTimeout(int connectTimeout) {
		this.connectTimeout = connectTimeout;
	}
	
	public String getFtpUrl() {
		return ftpUrl;
	}

	public void setFtpUrl(String ftpUrl) {
		this.ftpUrl = ftpUrl;
	}

	public int getFtpPort() {
		return ftpPort;
	}

	public void setFtpPort(int ftpPort) {
		this.ftpPort = ftpPort;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassWord() {
		return passWord;
	}

	public void setPassWord(String passWord) {
		this.passWord = passWord;
	}

	public String getCharset() {
		return charset;
	}

	public void setCharset(String charset) {
		this.charset = charset;
	}

	public String getDefaultWorkingDirectory() {
		return defaultWorkingDirectory;
	}

	public int getConnectTimeout() {
		return connectTimeout;
	}

	/**
	 * 删除文件
	 * 
	 * @param fileName
	 *            要删除的服务端文件 如：000/000.txt
	 * @return
	 */
	public boolean deleteFile(String fileName) {
		try {
			return ftpClient.deleteFile(fileName);
		} catch (IOException e) {
			LOGGER.error("[FTP工具类]删除服务端文件异常", e);
			return false;
		}
	}

	/**
	 * 获得FTP服务器目录下得文件列表
	 * 
	 * @param path
	 *            FTP服务器目录 如：000 根目录直接 "/"
	 * @return
	 */
	public List<String> getFileList(String path) {
		List<String> list = new ArrayList<String>();
		FTPFile[] flist = null;
		try {
			flist = ftpClient.listFiles(path);
			for (int i = 0; i < flist.length; i++) {
				if (!flist[i].isDirectory()) {
					list.add(flist[i].getName());
				}
			}
		} catch (IOException e) {
			LOGGER.error("[FTP工具类]获取文件列表异常", e);
		}
		return list;
	}

	/**
	 * 上传一个本地文件到FTP服务器
	 * 
	 * @param remoteDir
	 *            要上传到服务器的目录 如：000/
	 * @param remoteFileName
	 *            上传到服务器的文件名 如：000.txt
	 * @param localFile
	 *            本地文件 如:c:/000.txt
	 * @return
	 */
	public boolean upload(String remoteDir, String remoteFileName,
			File localFile) {
		InputStream stream = null;
		try {
			stream = new FileInputStream(localFile);
			// 设置本地模式
			LOGGER.info("ready to upload, now directory : "
					+ ftpClient.printWorkingDirectory());
			LOGGER.info("FTP default directory : "
					+ defaultWorkingDirectory);
			ftpClient.enterLocalPassiveMode();
			ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
			if (defaultWorkingDirectory != null
					&& !"".equals(defaultWorkingDirectory)
					&& remoteDir.startsWith(defaultWorkingDirectory)) {
				remoteDir = ROOT + StringUtils.substringAfter(remoteDir, defaultWorkingDirectory);
			}
			boolean b = ftpClient.changeWorkingDirectory(remoteDir);
			LOGGER.info("changed directory "
					+ remoteDir + " [" + b + "], now directory : " + ftpClient.printWorkingDirectory());
			LOGGER.info("file name : " + localFile.getName()
					+ " is going to be uploaded as : " + remoteFileName);
			LOGGER.info("upload:" + remoteDir + remoteFileName);
			return ftpClient.storeFile(defaultWorkingDirectory + remoteDir + remoteFileName, stream);
		} catch (Exception e) {
			LOGGER.error("【FTP工具类】上传文件异常", e);
			return false;
		} finally {
			try {
				if (stream != null)
					stream.close();
			} catch (IOException e) {
				LOGGER.error("【FTP工具类】上传文件异常", e);
			}
		}
	}

	/**
	 * 从FTP服务器下载一个文件到本地目录，文件名一致
	 * 
	 * @param remoteDir
	 *            服务端目录 如：000/
	 * @param remoteFileName
	 *            要下载的文件名
	 * @param localDir
	 *            本地目录 如：c:/000/
	 * @return
	 */
	public boolean download(String remoteDir, String remoteFileName,
			String localDir) {

		File file = new File(localDir + remoteFileName);
		OutputStream out = null;
		// InputStream input = null;
		try {
			if (!file.exists())
				file.createNewFile();
			out = new FileOutputStream(file);
			ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
			ftpClient.retrieveFile(remoteDir + remoteFileName, out);

			return true;
		} catch (Exception e) {
			LOGGER.error("[FTP工具类]下载文件异常", e);
			return false;
		} finally {
			try {
				// input.close();
				out.close();
			} catch (IOException e) {
				LOGGER.error("[FTP工具类]下载文件异常", e);
			}
		}
	}
	
	/**
	 * 重命名远端FTP文件名
	 * @param fromFileName
	 * @param toFileName
	 * @return
	 */
	public boolean renameFile(String fromFileName, String toFileName) {
		try {
			return ftpClient.rename(fromFileName, toFileName);
		} catch (IOException e) {
			LOGGER.error("[FTP工具类]重命名服务端文件异常", e);
			return false;
		}
	}
	
	public boolean changeToWorkDirectory(String path)
	{
	    try {
            return ftpClient.changeWorkingDirectory(path);
        } catch (IOException e) {
            LOGGER.error("[FTP工具类]切换工作目录异常", e);
            return false;
        }
	}
	
	
    public boolean createDirectory(String dateStr)
    {
        try
        {
            return ftpClient.makeDirectory(dateStr);
        }
        catch (IOException e)
        {
            LOGGER.error("[FTP工具类]创建目录异常", e);
            return false;
        }
    }
    
    public boolean reCreateDirecroty(String remote)
        throws IOException
      {
        String directory = remote.substring(0, remote.lastIndexOf("/") + 1);
        if ((!directory.equalsIgnoreCase("/")) && 
          (!ftpClient.changeWorkingDirectory(directory)))
        {
          int start = 0;
          int end = 0;
          if (directory.startsWith("/"))
            start = 1;
          else {
            start = 0;
          }
          end = directory.indexOf("/", start);
          do {
            String subDirectory = new String(remote.substring(start, end));
            if (!ftpClient.changeWorkingDirectory(subDirectory)) {
              if (ftpClient.makeDirectory(subDirectory)) {
                ftpClient.changeWorkingDirectory(subDirectory);
              } else {
                LOGGER.error("创建目录失败");
                return false;
              }
            }

            start = end + 1;
            end = directory.indexOf("/", start);
          }

          while (end > start);
        }

        return true;
      }
}